#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>//平台设备驱动


#include <linux/of.h> //of函数
#include <linux/of_gpio.h>  
#include <linux/gpio.h>
#include <dt-bindings/gpio/gpio.h>

/*
 * 配置dts控制多个gpio
 */

#if 0
// my add
	gpio-leds {
		compatible = "xyd-leds";
		status = "okay";
		led2-green {//led2-green
			gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>;  //GPIO_ACTIVE_LOW
			label = "green_led2";
		};

		led2-orange {//led2-orange
			gpios = <&gpio1 24 GPIO_ACTIVE_HIGH>;
			label = "green_led2";
		};
		
		led1 {
			gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>;
			label = "led1";
		};

    };




#endif 

int gpio_led1,gpio_led2_green,gpio_led2_orange; //led引脚号
static ssize_t
gpio_led1_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	return sprintf(buf, "%d\n", gpio_get_value(gpio_led1)); //可传到用户空间
}


static ssize_t
gpio_led2_green_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	return sprintf(buf, "%d\n", gpio_get_value(gpio_led2_green)); //可传到用户空间
}

static ssize_t
gpio_led2_orange_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	return sprintf(buf, "%d\n", gpio_get_value(gpio_led2_orange)); //可传到用户空间
}

static ssize_t
gpio_led1_store(struct device *dev, struct device_attribute *attr,
			  const char *buf, size_t count)
{
	int ret;
	int val;

	ret=kstrtoint(buf,10,&val); //将buf字符串转换为10进制数
	if(ret){
		printk("%d kstrtoint err\n",ret);
		return -1;
	}

	if(val==1){
		printk("%s,gpio pull up!\n",__FUNCTION__);
		gpio_direction_output(gpio_led1, val);
	}else if(val==0){
		printk("%s,gpio pull down\n",__FUNCTION__);
		gpio_direction_output(gpio_led1, val);
	}else {
		printk("I only support 0 or 1 ctrl led\n");
	}
	
	//printk("<xskj> call %s()\n",__FUNCTION__);
	return count;

}



static ssize_t
gpio_led2_green_store(struct device *dev, struct device_attribute *attr,
			  const char *buf, size_t count)
{
	int ret;
	int val;

	ret=kstrtoint(buf,10,&val); //将buf字符串转换为10进制数
	if(ret){
		printk("%d kstrtoint err\n",ret);
		return -1;
	}

	if(val==1){
		printk("%s,gpio pull up!\n",__FUNCTION__);
		gpio_direction_output(gpio_led2_green, val);
	}else if(val==0){
		printk("%s,gpio pull down\n",__FUNCTION__);
		gpio_direction_output(gpio_led2_green, val);
	}else {
		printk("I only support 0 or 1 ctrl led\n");
	}
	
	//printk("<xskj> call %s()\n",__FUNCTION__);
	return count;

}

static ssize_t
gpio_led2_orange_store(struct device *dev, struct device_attribute *attr,
			  const char *buf, size_t count)
{
	int ret;
	int val;

	ret=kstrtoint(buf,10,&val); //将buf字符串转换为10进制数
	if(ret){
		printk("%d kstrtoint err\n",ret);
		return -1;
	}

	if(val==1){
		printk("%s,gpio pull up!\n",__FUNCTION__);
		gpio_direction_output(gpio_led2_orange, val);
	}else if(val==0){
		printk("%s,gpio pull down\n",__FUNCTION__);
		gpio_direction_output(gpio_led2_orange, val);
	}else {
		printk("I only support 0 or 1 ctrl led\n");
	}
	
	//printk("<xskj> call %s()\n",__FUNCTION__);
	return count;

}			  



static DEVICE_ATTR(gpio_led1, 0664, gpio_led1_show,gpio_led1_store);
static DEVICE_ATTR(gpio_led2_green, 0664, gpio_led2_green_show,gpio_led2_green_store);
static DEVICE_ATTR(gpio_led2_orange, 0664, gpio_led2_orange_show,gpio_led2_orange_store);




// 当DTS节点和驱动的compatible匹配时调用
static int led_driver_probe(struct platform_device *pdev)
{
	//拿到和平台驱动匹配的设备树节点 myled_ctrl
	struct device_node *led_ctrl_node = pdev->dev.of_node;
	struct device_node *led1,*led2_green,*led2_orange;
	
	enum of_gpio_flags flags;


	led1 = of_get_child_by_name(led_ctrl_node , "led1"); //拿led_ctrl_node的子节点led1

	
	gpio_led1 = of_get_named_gpio_flags(led1, "gpios", 0, &flags);//读led1下gpios属性
	
	if (!gpio_is_valid(gpio_led1)) { //验证引脚号是否正确
    	printk("gpios: %d is invalid\n", gpio_led1); 
		return -ENODEV;
    }
	
	if (gpio_request(gpio_led1, "gpio_led1")) { // 申请使用权
        printk("gpio %d request failed!\n", gpio_led1);
        gpio_free(gpio_led1);
        return -ENODEV;
    }else {
		gpio_direction_output(gpio_led1, 0);//引脚输出设置低电平
		gpio_free(gpio_led1);
	}
	printk("<xyd> led1 gpios=%d\n",gpio_led1);
	printk("<xyd> flags==GPIO_ACTIVE_HIGH:%d\n",flags==GPIO_ACTIVE_HIGH);

	led2_green = of_get_child_by_name(led_ctrl_node , "led2-green"); //拿led_ctrl_node的子节点led3
	
	gpio_led2_green = of_get_named_gpio_flags(led2_green, "gpios", 0, &flags);//读led3下gpios属性
	
	if (!gpio_is_valid(gpio_led2_green)) { //验证引脚号是否正确
    	printk("gpios: %d is invalid\n", gpio_led2_green); 
		return -ENODEV;
    }
	
	if (gpio_request(gpio_led2_green, "gpio_led2_green")) { // 申请使用权
        printk("gpio %d request failed!\n", gpio_led2_green);
        gpio_free(gpio_led2_green);
        return -ENODEV;
    }else {
		gpio_direction_output(gpio_led2_green, 0);//引脚输出设置低电平
		gpio_free(gpio_led2_green);
	}
	printk("<xyd> led2 green gpios=%d\n",gpio_led2_green);
	printk("<xyd> flags==GPIO_ACTIVE_HIGH:%d\n",flags==GPIO_ACTIVE_HIGH);
	
	
	led2_orange = of_get_child_by_name(led_ctrl_node , "led2-orange");
	gpio_led2_orange = of_get_named_gpio_flags(led2_orange, "gpios", 0, &flags);
	if (!gpio_is_valid(gpio_led2_orange)) {
    	printk("gpios: %d is invalid\n", gpio_led2_orange); 
		return -ENODEV;
    }
	if (gpio_request(gpio_led2_orange, "gpio_led2_orange")) {
        printk("gpio %d request failed!\n", gpio_led2_green);
        gpio_free(gpio_led2_orange);
        return -ENODEV;
    }else {
		gpio_direction_output(gpio_led2_orange, 0);//设置低电平
		gpio_free(gpio_led2_orange);
	}
	printk("<xyd> led2 orange gpios=%d\n",gpio_led2_orange);
	printk("<xyd> flags==GPIO_ACTIVE_HIGH:%d\n",flags==GPIO_ACTIVE_HIGH);


	//创建sysfs下设备文件
	device_create_file(&pdev->dev, &dev_attr_gpio_led1);
	device_create_file(&pdev->dev, &dev_attr_gpio_led2_green);
	device_create_file(&pdev->dev, &dev_attr_gpio_led2_orange);

	printk("<xyd> call  %s()\n",__FUNCTION__);

	
	
	return 0;

}

static int led_driver_remove(struct platform_device *pdev)
{
	if (gpio_request(gpio_led2_green, "gpio_led2_green")) { // 申请使用权
        printk("gpio %d request failed!\n", gpio_led2_green);
        gpio_free(gpio_led2_green);
        return -ENODEV;
    }else {
		gpio_direction_output(gpio_led2_green, 0);//引脚输出设置低电平
		gpio_free(gpio_led2_green);
	}

	if (gpio_request(gpio_led2_orange, "gpio_led2_orange")) {
        printk("gpio %d request failed!\n", gpio_led2_green);
        gpio_free(gpio_led2_orange);
        return -ENODEV;
    }else {
		gpio_direction_output(gpio_led2_orange, 0);//设置低电平
		gpio_free(gpio_led2_orange);
	}

	
	device_remove_file(&pdev->dev, &dev_attr_gpio_led1);
	device_remove_file(&pdev->dev, &dev_attr_gpio_led2_green);
	device_remove_file(&pdev->dev, &dev_attr_gpio_led2_orange);
	
	printk("<xskj> call  %s()\n",__FUNCTION__);
	return 0;
}

static struct of_device_id led_ctrl_match_table [] ={
	//{ .compatible = "rk3399,myled_ctrl", }, // 应该和DTS节点的compatible属性一致

	{ .compatible = "xyd-leds", },
	{ },
};


static struct platform_driver  led_drv ={
	.probe = led_driver_probe,
	.remove = led_driver_remove,
	.driver = {
		.name = "myled",
		.of_match_table = led_ctrl_match_table,
	},

};


static int __init driver_mod_init(void)
{
	printk("<xyd>==========================\n");
	printk("<xyd> call led %s()\n",__FUNCTION__);
	printk("<xyd>==========================\n");
	return platform_driver_register(&led_drv);
}

static void __exit driver_mod_exit(void)
{
	printk("<xyd> call %s()\n",__FUNCTION__);
	platform_driver_unregister(&led_drv);
}

module_init(driver_mod_init);
module_exit(driver_mod_exit);
MODULE_LICENSE("GPL");

